using SG3L_RAG.Application.Interfaces;
using SG3L_RAG.Domain.Entities;
using SG3L_RAG.Domain.Repositories;

namespace SG3L_RAG.Application.Services
{
    public class DocumentChunkService : IDocumentChunkService
    {
        private readonly IRepository<DocumentChunk> _documentChunkRepository;

        public DocumentChunkService(IRepository<DocumentChunk> documentChunkRepository)
        {
            _documentChunkRepository = documentChunkRepository;
        }

        public async Task<DocumentChunk?> GetByIdAsync(Guid id)
        {
            return await _documentChunkRepository.GetByIdAsync(id);
        }

        public async Task<IEnumerable<DocumentChunk>> GetAllAsync()
        {
            return await _documentChunkRepository.GetAllAsync();
        }

        public async Task<DocumentChunk> CreateAsync(Guid documentId, int chunkIndex, string content, float[] vector)
        {
            var documentChunk = DocumentChunk.Create(documentId, chunkIndex, content, vector);
            await _documentChunkRepository.AddAsync(documentChunk);
            return documentChunk;
        }

        public async Task UpdateAsync(DocumentChunk documentChunk)
        {
            await _documentChunkRepository.UpdateAsync(documentChunk);
        }

        public async Task DeleteAsync(Guid id)
        {
            await _documentChunkRepository.DeleteAsync(id);
        }

        public async Task<IEnumerable<DocumentChunk>> GetByDocumentIdAsync(Guid documentId)
        {
            var chunks = await _documentChunkRepository.GetAllAsync();
            return chunks.Where(c => c.DocumentId == documentId);
        }

        public async Task<IEnumerable<DocumentChunk>> SearchByVectorAsync(float[] queryVector, int topK = 10)
        {
            var chunks = await _documentChunkRepository.GetAllAsync();
            
            // 计算每个分片与查询向量的相似度
            var scoredChunks = chunks
                .Where(c => c.Vector != null && c.Vector.Length > 0)
                .Select(c => new
                {
                    Chunk = c,
                    Similarity = c.CosineSimilarity(queryVector)
                })
                .Where(item => item.Similarity > 0.1f) // 过滤掉相似度太低的
                .OrderByDescending(item => item.Similarity)
                .Take(topK)
                .Select(item => item.Chunk);

            return scoredChunks;
        }

        public async Task<IEnumerable<DocumentChunk>> GetChunksByRangeAsync(Guid documentId, int startIndex, int endIndex)
        {
            var chunks = await GetByDocumentIdAsync(documentId);
            return chunks.Where(c => c.ChunkIndex >= startIndex && c.ChunkIndex <= endIndex);
        }

        public async Task BatchCreateAsync(List<DocumentChunk> chunks)
        {
            await _documentChunkRepository.AddRangeAsync(chunks);
        }

        public async Task DeleteByDocumentIdAsync(Guid documentId)
        {
            var chunks = await GetByDocumentIdAsync(documentId);
            var chunkIds = chunks.Select(c => c.Id);
            await _documentChunkRepository.DeleteRangeAsync(chunkIds);
        }
    }
}
